home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1992 June: ROMin Holiday / ADC Developer CD (1992-06) (''ROMin Holiday'')_iso / Developer Connection - 06-1992.iso / Development Platforms / LISP Related / U. Mass AI & LISP Tools / MODULES / DACTN / DACTNS.lisp < prev   
Encoding:
Text File  |  1990-06-24  |  16.8 KB  |  384 lines  |  [TEXT/CCL ]

  1. ; (c) Copyright 1990 by University of Massachusetts. All rights reserved.
  2. ; This software was conceived, designed, and written by Dan Suthers 
  3. ; while supported by the National Science Foundation under grant number
  4. ; MDR 8751362, and by a fellowship from Apple Computer, Inc., Cupertino,
  5. ; CA.  Partial support was also received from the Office of Naval Research
  6. ; under a University Research Initiative Grant, contract N00014-86-K-0764.
  7. ; Mr. Suthers created this software under his own initiative while in an 
  8. ; academic relationship with the University of Massachusetts.  The above
  9. ; copyright notice was a condition placed by University lawyers on approval
  10. ; of distribution of this software by Apple Computer, and is not meant to
  11. ; imply that this software was created in an employment or "work for hire"
  12. ; relationship between the University and Mr. Suthers.
  13. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  14. ; File:         DACTNS.lisp
  15. ; Author:       Dan Suthers
  16. ; Created:      08-Aug-88 20:49:25
  17. ; Modified:     22-Jun-90 02:37:09 (Dan Suthers)
  18. ; Language:     Common Lisp
  19. ; Package:      DACTN
  20. ;
  21. ; Description:  Defines recursive DACTNs and interpreter.
  22. ;
  23. ; (c) Copyright 1988, by Daniel D. Suthers
  24. ;                        Department of Computer and Information Science
  25. ;                        University of Massachusetts
  26. ;                        Amherst, Massachusetts 01003
  27. ;
  28. ; This software was conceived, designed, and written by Dan Suthers 
  29. ; while supported by the National Science Foundation under grant number
  30. ; MDR 8751362, and by a fellowship from Apple Computer, Inc., Cupertino,
  31. ; CA.  Partial support was also received from the Office of Naval Research
  32. ; under a University Research Initiative Grant, contract N00014-86-K-0764.
  33. ; I wish to acknowledge the generous support of Beverly Woolf, who obtained 
  34. ; the above grants and encouraged me to pursue my own research interests in
  35. ; her lab.  This work would not have been possible without the resources and
  36. ; stimulating environment of the Computer and Information Science department.
  37. ;
  38. ; Permission to use, modify, and distribute this software is granted subject 
  39. ; to the following restrictions and understandings:
  40. ; 1. The file header, including this notice, shall be retained, and may be
  41. ;    extended to include documentation of modifications to the software.
  42. ; 2. This material is for nonprofit educational and research purposes only.
  43. ;    Users are requested, but not required, to inform Mr. Suthers of any 
  44. ;    noteworthy uses of this software.
  45. ; 3. Mr. Suthers and the University of Massachusetts make no warrantee or
  46. ;    representation that the operation of this software will be error free,
  47. ;    and are under no obligation to provide any services.
  48. ; 4. Any user of such software agrees to indemnify and hold harmless Mr.
  49. ;    Suthers and the University of Massachusetts from all claims arising 
  50. ;    out of the use or misuse of this software, or arising out of any 
  51. ;    accident, injury, or damage whatsoever, and from all costs, counsel
  52. ;    fees, and liabilities incurred in or about any such claim, action, or
  53. ;    proceeding brought thereon.
  54. ; 5. All materials and reports developed as a consequence of the use of 
  55. ;    this software shall duly acknowledge such use, in accordance with
  56. ;    the usual standards of acknowledging credit in academic research.
  57. ;
  58. ; Status:       Usable, though I'd do it differently now.
  59. ;               Needs compiler, better handling of re-entrant DACTNs.
  60. ;
  61. ; Changes:      
  62. ;   04-Sep-88 Interpreter does not try to interpret DACTN with no start node.
  63. ;   26-Oct-88 Interpreter signals cerror if start node is specified but not
  64. ;     defined in dactn-nodes; trace indented.
  65. ;   01-Nov-88 Updated for SM changes.
  66. ;   20-Dec-88 Added :edit-in-package :user to DST's.
  67. ;
  68. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  69. ; Comments
  70. ; Nodes and arcs do not exist independently of the containing DACTN, so 
  71. ; they are not represented as separate SM objects.  In contrast, the tests
  72. ; on the arcs may be reused across DACTNs (they constitute a terminology
  73. ; for the conditional predicates), so are represented as DACTN-TESTs.  Ditto
  74. ; for the actions.
  75. ;
  76. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  77.  
  78. (in-package :DACTN)
  79.  
  80. (export '(
  81.           *trace-dactns*
  82.  
  83.           dactn
  84.           initialize-dactns
  85.           initialize-dactn
  86.           interpret-dactn
  87.           run-dactn
  88.  
  89.           dactn-test
  90.           initialize-dactn-test
  91.  
  92.           dactn-action
  93.           initialize-dactn-action
  94.  
  95.           ))
  96.  
  97. (require :SM)
  98.  
  99. ;;; To get past ccl compiler bug: it seems to hit sm:symbols before
  100. ;;; executing the require that creates the package, and gives a "no
  101. ;;; package WIND" error.
  102. (use-package :sm)
  103.  
  104. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  105.  
  106. (defconstant *ARC-TYPES* '(:goto :exit))
  107.  
  108. ;;; DACTN-NODEs are not implemented in SM as they conceptually  do not 
  109. ;;; exist outside of a given DACTN.  See the documentation under DACTN.
  110. ;;; ARG-GEN not compiled so the structure will not contain unreadable forms.
  111.  
  112. (defstruct (DACTN-NODE (:type list)) ; prints better to editor windows.
  113.   (ACTION           nil                                          :type list)
  114.   (ARG-GEN          '(lambda (node) (declare (ignore node)) nil) :type list)
  115.   (STATE            '(:state nil)                                :type list)
  116.   (ARCS             nil                                          :type list))
  117.  
  118.  
  119. (sm:dst (DACTN 
  120.          (:reusable nil) 
  121.          (:redefine t)
  122.          (:sort-instances t)
  123.          (:edit-in-package :user)
  124.          (:after-edit (lambda (d) (initialize-dactn d)))
  125.          (:comments "
  126.   Discourse ACTion Networks, written to work with the View Retriever.  Each
  127.   network is defined by a set of nodes, where each node consists of an action
  128.   and a set of arcs which are candidate ways to traverse out of the node.  One
  129.   node is designated the start node.  DACTNs are compiled into an efficient
  130.   function called by RUN-DACTN, but may be interpreted by INTERPRET-DACTN for 
  131.   debugging."))
  132.  
  133.         (NODES      nil
  134.                     :type list
  135.                     :comments "
  136.     An association list of node names to the definition of the node, which is
  137.     a DACTN-NODE structure.  (SM is not used for nodes because they are not 
  138.     visible outside of a given DACTN.)  The latter structure contains the
  139.     following slots:
  140.       ACTION  - (:action <action-name>) or (:dactn <dactn-name>).
  141.       ARG-GEN - Lambda of one argument which generates the arguments to be
  142.         given to the ACTION.  The argument is a list of form (:state <state>).
  143.         A setf of the second element will modify the node's state.
  144.       STATE   - A list of form (:state <state>).  Initially <state> is nil.
  145.       ARCS    - An association list of DACTN-TESTs to arcs, which are of form
  146.         (:goto <node-name>) or (:exit). Thus each entry in this list will look
  147.         like (<dactn-test-name> <arc-action-keyword> [<argument>]).  The arc
  148.         in the first one whose CAR succeeds will be traversed.
  149.     When a node is entered, (1) ARG-GEN is called on the state to generate a list
  150.     of arguments; (2) the indicated ACTION is called on these arguments; (3) the
  151.     list of ARCS is scanned to find the first one whose DACTN-TEST returns T when
  152.     called on the state value; and (4) this arc is traversed by interpreting its 
  153.     keyword.")
  154.  
  155.         (START-NODE nil
  156.                     :type symbol
  157.                     :comments "
  158.     The name of the start node for this DACTN.  Its action is always executed.
  159.     when the DACTN is run.  It must be defined in NODES.")
  160.  
  161.         (FUNCTION #'(lambda (d ns)
  162.                       (error "Uncompiled DACTN-FUNCTION given ~S and ~S." d ns))
  163.                   :type function
  164.                   :computed t
  165.                   :comments "
  166.     This is the compiled version of the DACTN, used to save the time of 
  167.     searching association lists and interpreting actions.  INITIALIZE-DACTN
  168.     fills this slot. The function takes no arguments, and executes the DACTN
  169.     when funcalled.")
  170.  
  171.         (TYPE       nil
  172.                     :type symbol
  173.                     :comments "
  174.     This is a place to put a symbol categorizing the DACTN, to aid accessing and
  175.     editing them.  The use of this slot is application specific.")
  176.  
  177.         (COMMENTS "" :type string))
  178.  
  179.  
  180. (sm:dst (DACTN-TEST
  181.          (:reusable nil)
  182.          (:redefine t)
  183.          (:sort-instances t)
  184.          (:edit-in-package :user)
  185.          (:after-edit (lambda (dt) (initialize-dactn-test dt)))
  186.          (:comments "
  187.   These are reusable tests of the state of the discourse and user models, used to
  188.   determine which arc to take in a DACTN.  They are given the current state value 
  189.   (the second element of the STATE slot) of the node as their only argument."))
  190.  
  191.         (FORM '(lambda (state) nil)
  192.               :type list
  193.               :comments "
  194.     A lambda list of one argument, the STATE, which returns T iff whatever it tests
  195.     for is true.  Presumable some of these access the discourse and user models.")
  196.  
  197.         (COMPILED-FORM #'(lambda (state)
  198.                            (error "Uncompiled DACTN-TEST-FORM given ~S" state))
  199.                        :type function
  200.                        :computed t)
  201.  
  202.         (TYPE     nil
  203.                   :type symbol
  204.                   :comments "
  205.     This is a place to put a symbol categorizing the DACTN-TEST, to aid accessing and
  206.     editing them.  The use of this slot is application specific.  See also INFO.")
  207.  
  208.         (INFO     nil 
  209.                   :comments "
  210.     This is a place to put arbitrary info about the test.  See also TYPE.")
  211.  
  212.         (COMMENTS "" :type string))
  213.  
  214.  
  215. (sm:dst (DACTN-ACTION
  216.          (:reusable nil)
  217.          (:redefine t)
  218.          (:sort-instances t)
  219.          (:edit-in-package :user)
  220.          (:after-edit (lambda (da) (initialize-dactn-action da)))
  221.          (:comments "
  222.   Each of these defines an action in the underlying application.  The names
  223.   of these objects are the arguments to the :dactn-action specifier in DACTN
  224.   arcs."))
  225.  
  226.         (FORM '(lambda (args)  nil)
  227.               :type list
  228.               :comments "
  229.     A lambda list of one argument which executes the intended action.  The
  230.     arguments are the list of arguments given to the action in the arc.")
  231.  
  232.  
  233.         (COMPILED-FORM #'(lambda (args) (error "Uncompiled DACTN-ACTION given ~S" args))
  234.                        :type function
  235.                        :computed t)
  236.  
  237.         (TYPE     nil
  238.                   :type symbol
  239.                   :comments "
  240.     This is a place to put a symbol categorizing the DACTN-ACTION, to aid accessing and
  241.     editing them.  The use of this slot is application specific.")
  242.  
  243.         (INFO     nil 
  244.                   :comments "
  245.     This is a place to put arbitrary info about the action.  See also TYPE.")
  246.  
  247.         (COMMENTS "" :type string))
  248.  
  249. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  250.  
  251. (defun INITIALIZE-DACTNS ()
  252.   (format *trace-output* "~&[Initializing DACTN-TESTs")
  253.   (dolist (dt (sm:instances 'dactn-test))
  254.     (declare (symbol dt))
  255.     (initialize-dactn-test dt))
  256.   (format *trace-output* "]~%[Initializing DACTN-ACTIONs")
  257.   (dolist (da (sm:instances 'dactn-action))
  258.     (declare (symbol da))
  259.     (initialize-dactn-action da))
  260.   (format *trace-output* "]~%[Initializing DACTNs")
  261.   (dolist (d (sm:instances 'dactn))
  262.     (declare (symbol d))
  263.     (initialize-dactn d))
  264.   (format *trace-output* "]"))
  265.  
  266. (defun INITIALIZE-DACTN-TEST (dt)
  267.   (let ((dactn-test (sm:gets 'dactn-test dt)))
  268.     (setf (dactn-test-compiled-form dactn-test)
  269.           (compile nil (dactn-test-form dactn-test)))))
  270.  
  271. (defun INITIALIZE-DACTN-ACTION (da)
  272.   (let ((dactn-action (sm:gets 'dactn-action da)))
  273.     (setf (dactn-action-compiled-form dactn-action)
  274.           (compile nil (dactn-action-form dactn-action)))))
  275.  
  276. (defun INITIALIZE-DACTN (d) nil)
  277. ;  (let ((dactn (sm:gets 'dactn d)))
  278. ;    (dolist (name+struct (dactn-nodes dactn))
  279. ;      (declare (cons name+struct))
  280. ;      (setf (dactn-compiled-chooser dactn)
  281. ;            (compile nil
  282. ;                     `(lambda ()
  283. ;                        (interpret-action
  284. ;                         (funcall (dactn-compiled-chooser (sm:gets 'dactn dactn))
  285. ;                                  (mapcan #'(lambda (t+a)
  286. ;                                              (declare (cons t+a))
  287. ;                                              (if (funcall (dactn-test-compiled-form 
  288. ;                                                            (sm:gets 'dactn-test (car t+a))))
  289. ;                                                (list t+a)))
  290. ;                                          (dactn-arcs (sm:gets 'dactn dactn))))))))))
  291.  
  292. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  293.  
  294. (defvar *TRACE-DACTNS* nil)
  295.  
  296. (defun INTERPRET-DACTN (dactn)
  297.   "interpret-dactn <dactn>                                          [Function]
  298.   Interprets the dactn, without using the compiled dactn-function.  Also
  299.   uses uncompiled DACTN-TEST-FORM, DACTN-NODE-ARG-GEN, and DACTN-ACTION-FORM.
  300.   Useful for debugging purposes."
  301.   (check-type dactn symbol)
  302.   (assert (sm:gets 'dactn dactn) (dactn) "~S is not a known DACTN." dactn)
  303.   (let* ((dactn-struct (sm:gets 'dactn dactn))
  304.          (start-node (dactn-start-node dactn-struct))
  305.          (node-struct
  306.           (cdr (assoc start-node (dactn-nodes dactn-struct)))))
  307.     (declare (type dactn dactn-struct))
  308.  
  309.     ;; This would have saved me some time if it was here earlier ...
  310.     (if (and start-node (null node-struct)) 
  311.       (cerror "Will exit the DACTN but continue execution."
  312.               "[INTERPRET-DACTN] Specified start node ~S for DACTN ~S is not defined."
  313.               start-node dactn))
  314.  
  315.     (when node-struct
  316.       (when *trace-dactns*
  317.         (if (not (numberp *trace-dactns*)) (setq *trace-dactns* 0))
  318.         (format *trace-output* "~&")
  319.         (dotimes (x *trace-dactns*) (format *trace-output* " "))
  320.         (format *trace-output* "[INTERPRET-DACTN] Starting ~A at ~A" 
  321.                 dactn (dactn-start-node dactn-struct))
  322.         (incf *trace-dactns*))
  323.  
  324.       ;; Interpretation consists of traversing arcs and interpreting nodes encountered.
  325.       ;; If an :exit arc is executed in this dactn, returns to here immediately.
  326.       (interpret-dactn-nodes dactn-struct node-struct)
  327.  
  328.       (when *trace-dactns* 
  329.         (decf *trace-dactns*)
  330.         (format *trace-output* "~&")
  331.         (dotimes (x *trace-dactns*) (format *trace-output* " "))
  332.         (format *trace-output* "[INTERPRET-DACTN] Leaving  ~A"
  333.                 dactn (dactn-start-node dactn-struct))))))
  334.  
  335. (defun INTERPRET-DACTN-NODES (dactn-struct node-struct)
  336.   (declare (type dactn dactn-struct) (type dactn-node node-struct))
  337.   ;; Loop to repeat on new dactn nodes (saving cost of recursion).
  338.   (loop
  339.     ;; Run the action of the node.
  340.     (case (first (dactn-node-action node-struct))
  341.       ((nil) (cerror "Will ignore." "Unspecified action for node ~S." node-struct))
  342.       ;; Action called on arguments generated by arg-gen, which tests & sets state.
  343.       ((:action)
  344.        (funcall (dactn-action-form (sm:gets 'dactn-action
  345.                                             (second (dactn-node-action node-struct))))
  346.                 (funcall (dactn-node-arg-gen node-struct) 
  347.                          (dactn-node-state node-struct))))
  348.       ((:dactn) (interpret-dactn (second (dactn-node-action node-struct)))))
  349.     ;; Find the first arc whose test succeeds when called on the node's state.
  350.     (let ((arc (find-if #'(lambda (arc) (declare (list arc))
  351.                            (funcall (dactn-test-form (sm:gets 'dactn-test (first arc)))
  352.                                     (dactn-node-state node-struct)))
  353.                         (dactn-node-arcs node-struct))))
  354.       ;; Traverse this arc as specified by its keyword.
  355.       (if arc
  356.         (ecase (second arc)
  357.           ;; Go To is to another node in the dactn: (<test> :goto <node>)
  358.           ((:goto)
  359.            (when *trace-dactns* 
  360.              (format *trace-output* "~&")
  361.              (dotimes (x *trace-dactns*) (format *trace-output* " "))
  362.              (format *trace-output* "[INTERPRET-DACTN-NODES] Going to node ~A" 
  363.                      (third arc)))
  364.            (setq node-struct (cdr (assoc (third arc) (dactn-nodes dactn-struct)))))
  365.           ;; Exit returns from the dactn, so requires a throw.
  366.           ((:exit) (return nil)))
  367.         (return nil)))))
  368.  
  369. ;;; Right now these parallel the INTERPRET- functions, but will be
  370. ;;; converted to simply invoke a truly compiled version, which simply:
  371. ;;;    (funcall (dactn-function (sm:gets 'dactn dactn)) dactn)
  372.  
  373. (defun RUN-DACTN (dactn)
  374.   "run-dactn <dactn>                                                [Function]
  375.   Runs the DACTN, using its compiled functions."
  376.   (check-type dactn symbol)
  377.   (assert (sm:gets 'dactn dactn) (dactn) "~S is not a known DACTN.")
  378.   (cerror "returns" "RUN-DACTN not implemented, use INTERPRET-DACTN for ~S." dactn))
  379.  
  380. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  381. (provide :DACTNS)
  382. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  383. ;;; EOF